package com.haibara.codesubmiteval.judge.strategy;

import cn.hutool.core.util.StrUtil;
import com.haibara.codesubmiteval.constant.FileConstant;
import com.haibara.codesubmiteval.model.entity.QuestionCase;
import com.haibara.codesubmiteval.model.enums.JudgeResultEnum;
import com.haibara.codesubmiteval.utils.FileUtil;
import lombok.extern.slf4j.Slf4j;

import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

@Slf4j
public class DefaultJudgeStrategy implements JudgeStrategy {

    /**
     * 根据判题上下文对程序输出进行判题，并得到结果
     *
     * @param judgeContext 判题上下文
     * @return 判题结果 ：Accepted | Wrong Answer | Memory Limit Exceeded | Time Limit Exceeded
     */
    @Override
    public JudgeResultEnum doJudge(JudgeContext judgeContext) {
        Long userId = judgeContext.getUserId();
        List<QuestionCase> questionCaseList = judgeContext.getQuestionCaseList();
        Long questionId = questionCaseList.get(0).getQuestionId();
        List<String> outputList = judgeContext.getOutputList();
        List<String> correctOutputList = questionCaseList.stream().map(QuestionCase::getOutput).toList();
        List<String> fileOutputList = judgeContext.getFileOutputList();
        List<String> correctFileOutputList = questionCaseList.stream().map(QuestionCase::getFileOutput).toList();
        Integer timeUsed = judgeContext.getTimeUsed();
        Integer memoryUsed = judgeContext.getMemoryUsed();
        Integer timeLimit = judgeContext.getTimeLimit();
        Integer memoryLimit = judgeContext.getMemoryLimit();
        // 根据沙箱执行结果，设置题目的判题状态和信息
        // 1.1 判断outputList内容与correctOutputList是否一致
        if (correctOutputList.size() != outputList.size()) {
            return JudgeResultEnum.WRONG_ANSWER;
        }
        for (int i = 0; i < correctOutputList.size(); i++) {
            // 消除\n换行符
            String output = outputList.get(i).stripTrailing();
            String correctOutput = correctOutputList.get(i);
            if (StrUtil.isBlankIfStr(correctOutput)) {
                if (!StrUtil.isBlankIfStr(output)) {
                    return JudgeResultEnum.WRONG_ANSWER;
                }
            } else {
                if (!correctOutput.equals(output)) {
                    return JudgeResultEnum.WRONG_ANSWER;
                }
            }
        }
        // 1.2 判断fileOutputList内容与correctFileOutputList是否一致
        for (int i = 0; i < fileOutputList.size(); i++) {
            String fileOutput = fileOutputList.get(i);
            String correctFileOutput = correctFileOutputList.get(i);
            if (!StrUtil.isBlankIfStr(fileOutput) && !StrUtil.isBlankIfStr(correctFileOutput)) {
                Path userOutputFilePath = Path.of(FileConstant.getUserOutputFilePath(userId, questionId), fileOutput);
                if (!Files.exists(userOutputFilePath)) {
                    // 代表用户把用户输出文件删除，报错
                    return JudgeResultEnum.RUNTIME_ERROR;
                }
                boolean result;
                result = FileUtil.compareTwoFile(
                        FileConstant.getUserOutputFilePath(userId, questionId),
                        fileOutput,
                        FileConstant.getOutputFilePath(questionId, questionCaseList.get(i).getId()),
                        correctFileOutput
                );
                if (!result) {
                    return JudgeResultEnum.WRONG_ANSWER;
                }
            }
        }
        // 2.判断时间消耗和内存消耗是否在限制之内
        if (memoryUsed > memoryLimit) {
            return JudgeResultEnum.MEMORY_LIMIT_EXCEEDED;
        }
        if (timeUsed > timeLimit) {
            return JudgeResultEnum.TIME_LIMIT_EXCEEDED;
        }
        return JudgeResultEnum.ACCEPTED;
    }
}
